﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAPI_DEMO.Filter;
using WebAPI_DEMO.Models;
using WebAPI_DEMO.Models.Database;
using WebAPI_DEMO.Service;

namespace WebAPI_DEMO.Controllers
{
    //配置访问路由
    /// <summary>
    /// 商品控制器
    /// </summary>
    /// 控制器的路由 api/控制器名字(Good)/方法名
    [Route("api/[controller]/[action]")]
    //API控制器
    [ApiController]
    [AuthorizeFilter]
    public class GoodController : ControllerBase
    {
        //定义数据库上下文
        private readonly Store_2022Context _db;

        //定义数据服务类  类型         变量名 _开头  代表全局变量
        private readonly IDataServices _dataService;
        private readonly ISingletonService _singletonService;
        private readonly ITransientService _transientService;
        private readonly IScopedService _scopedService;
        /// <summary>
        /// 构造方法 构造注入
        /// 把数据库上下文初始化
        /// </summary>
        public GoodController(Store_2022Context db, IDataServices dataServices, ISingletonService singletonService, ITransientService transientService, IScopedService scopedService)
        {
            _db = db;
            _dataService = dataServices;
            _singletonService = singletonService;
            _transientService = transientService;
            _scopedService = scopedService;
        }

        //添加第一个接口 添加商品
        //要有商品数据  用户输入 前端调用API接口 传递给后端（调用接口过程）
        /// <summary>
        /// 新增产品
        /// </summary>
        /// <param name="good"></param>
        /// <returns></returns>
        /// 定义支持的请求方式（使用了post请求）
        [HttpPost]
        //				  此类型看返回的结果是什么类型就定义什么类型)
        //访问权限public  返回参数数据类型   方法名AddGood (请求参数的数据类型 变量)
        // 控制器的路由 url 接口的地址 api/Good/AddGood
        [AuthorizeFilter]
        public string AddGood(Good good)
        {
            //后端 做的事情
            //业务逻辑编写 添加商品
            //把商品添加到数据

            //数据库上下.操作的表名.操作的方法(参数)
            _db.Goods.Add(good);
            //保存更改 row影响条数
            var row = _db.SaveChanges();
            //数据库新增成功了
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }

        /// <summary>
        /// 新增产品 自定请求类
        /// 站点名/api/Good/AddGood2
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string AddGood2(AddGood2 request)
        {
            //开始 业务逻辑

            //手动转换类 把请求类 转换 成 数据库模型类
            var good = new Good
            {
                Name = request.Name,
                Cover = request.Cover,
                CateId = request.CateId,
                Price = request.Price,
                Stock = request.Stock,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now,
            };

            //数据库上下.操作的表名.操作的方法(参数)
            _db.Goods.Add(good);
            //保存更改 row影响条数
            var row = _db.SaveChanges();
            //数据库新增成功了
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }

        /// <summary>
        /// 增加商品方法 URL参数请求
        /// </summary>
        /// <param name="name"></param>
        /// <param name="cover"></param>
        /// <param name="cateId"></param>
        /// <param name="price"></param>
        /// <param name="stock"></param>
        /// <returns></returns>
        //第三种方式 URL参数
        //api/good/AddGood3?name=xxxx&cateid=2&cover=xxxx   name cover  price stock
        [HttpGet]
        public string AddGood3(string name, string cover, int cateId, decimal price, int stock)
        {
            //把参数 转换 成商品模型类
            var good = new Good
            {
                Name = name,
                CateId = cateId,
                Cover = cover,
                Price = price,
                Stock = stock,
                CreateTime = DateTime.Now,
                UpdateTime = DateTime.Now,
            };
            //数据库上下.操作的表名.操作的方法(参数)
            _db.Goods.Add(good);
            //保存更改 row影响条数
            var row = _db.SaveChanges();
            //数据库新增成功了
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }

        /// <summary>
        /// 新增产品 模型验证
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public string AddGood4(AddGood2 request)
        {
            //模型验证
            //！false=true
            if (!ModelState.IsValid)
            {
                // ModelState[ModelState.Keys.FirstOrDefault()].Errors.FirstOrDefault();
                return "数据错误";
            }
            //请求参数的规则判断
            //开始 业务逻辑
            //加需求 判断商品名称 不能为空 如果为空 做出提示
            if (string.IsNullOrEmpty(request.Name))
                return "商品名称不能为空";

            if (string.IsNullOrEmpty(request.Cover))
                return "封面图不能为空";

            if (request.Name.Length > 50)
                return "商品名称长度不能大于50";

            if (request.Price <= 0)
                return "商品价格不能少于等于0";

            //手动转换类 把请求类 转换 成 数据库模型类
            _db.Goods.Add(new Good()
            {
                Name = request.Name,
                CateId = request.CateId,
                Cover = request.Cover,
                CreateTime = DateTime.Now,
                Price = request.Price,
                Stock = request.Stock,
            });
            var row = _db.SaveChanges();
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }

        /// <summary>
        /// 新增分类 数据库模型请求
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        [HttpPost]
        public string AddCategory(Category category)
        {
            _db.Categories.Add(category);
            var row = _db.SaveChanges();
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }
        /// <summary>
        /// 新增分类2  自定义类请求
        /// </summary>
        /// <param name="category"></param>
        /// <returns></returns>
        [HttpPost]
        public string AddCategory2(Category category)
        {
            var model = new Category
            {
                CateName = category.CateName
            };
            _db.Categories.Add(model);
            var row = _db.SaveChanges();
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }
        /// <summary>
        /// 新增分类3  URL参数请求
        /// </summary>
        /// <param name="cateName"></param>
        /// <returns></returns>
        [HttpPost]
        public string AddCategory3(string cateName)
        {
            var model = new Category
            {
                CateName = cateName
            };
            _db.Categories.Add(model);
            var row = _db.SaveChanges();
            if (row > 0)
                return "新增成功";
            return "新增失败";
        }

        //重点 怎么写一个接口
        //有什么

        //1、支持的请求方式
        //[HttpGet]  查询接口
        //[HttpPost] 增删改

        //2public 访问权限

        //3方法的返回类型string  根据需求、返回值决定类型是什么

        //4请求方法名 决定请求的路径

        //5请求参数 不同的类型

        //6业务逻辑 根据接口需求 //登录 注册

        //7返回参数 根据接口需求 return 

        /// <summary>
        /// 更新产品 自定义类请求
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        //更新接口 更新产品 更新哪个商品 更新成什么
        [HttpPost]
        public string UpdateGood(UpdateGood request)
        {
            //6业务逻辑 根据需求 更新哪个商品 更新成什么
            //查询出需要更新的商品 根据条件查询第一个商品
            var good = _db.Goods.FirstOrDefault(x => x.Id == request.Id);
            if (good == null)
                return "商品为空";

            //把前端传过来数据赋值
            good.Name = request.Name;
            good.Cover = request.Cover;
            good.CateId = request.CateId;
            good.Price = request.Price;
            good.Stock = request.Stock;
            good.UpdateTime = DateTime.Now;

            //数据库更新操作
            _db.Goods.Update(good);
            var row = _db.SaveChanges();
            if (row > 0)
                return "更新成功";
            return "更新失败";
        }

        /// <summary>
        /// 删除商品
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public string DeleteGood(int id)
        {
            //删除哪个商品 查询指定商品
            var good = _db.Goods.FirstOrDefault(x => x.Id == id);
            if (good == null)
                return "商品为空";
            _db.Remove(good);
            var row = _db.SaveChanges();
            if (row > 0)
                return "删除成功";
            return "删除失败";
        }

        //练习：完成分类的更新 和 删除 接口
        //方法
        /// <summary>
        /// 更新分类接口
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public string UpdateCategories(UpdateCategory req)
        {
            var cate = _db.Categories.FirstOrDefault(x => x.Id == req.Id);
            if (cate == null)
                return "数据不存在";
            //对分类对象进行赋值
            cate.CateName = req.CateName;

            _db.Categories.Update(cate);
            var row = _db.SaveChanges();
            if (row > 0)
                return "更新成功";
            return "更新失败";
        }
        /// <summary>
        /// 删除指定分类
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public string DeleteCategory(int id)
        {
            //先查询出需要删除的商品
            var cate = _db.Categories.FirstOrDefault(x => x.Id == id);
            if (cate == null)
                return "数据不存在";

            _db.Categories.Remove(cate);
            var row = _db.SaveChanges();
            if (row > 0)
                return "删除成功";
            return "删除失败";
        }

        /// <summary>
        /// 获取所有产品接口
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public List<Good> GetGoodAllList()
        {
            //业务逻辑
            var list = _db.Goods.ToList();
            //返回list的值
            return list;
        }

        /// <summary>
        /// 根据请求体参数获取产品
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public List<Good> GetGoodList1(GetGoodList1Request request)
        {
            //获取商品操作
            var list = _db.Goods.AsQueryable();
            //如果查询的分类Id>0 
            if (request.CateId > 0)
                list = list.Where(x => x.CateId == request.CateId);
            //如果查询的关键字不为空
            if (!string.IsNullOrEmpty(request.Keyword))
                list = list.Where(x => x.Name.Contains(request.Keyword));
            return list.ToList();
        }

        /// <summary>
        /// 根据Get参数获取产品
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public List<Good> GetGoodAllList2(string keyword, int cateId)
        {
            //获取商品操作
            var list = _db.Goods.AsQueryable();
            //如果查询的分类Id>0 
            if (cateId > 0)
                list = list.Where(x => x.CateId == cateId);
            //如果查询的关键字不为空
            if (!string.IsNullOrEmpty(keyword))
                list = list.Where(x => x.Name.Contains(keyword));
            return list.ToList();
        }

        //练习 编写查询分类接口 并且根据分类名称筛选

        /// <summary>
        /// 返回连表后的模型数据
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        //在指定方法的头部增加筛选器
        [CustomerResourceFilterAttribute]
        public List<GoodModel> GetGoodAllList3(string keyword, int cateId)
        {
            //获取商品操作
            var goods = _db.Goods.AsQueryable();

            //如果查询的分类Id>0 
            if (cateId > 0)
                goods = goods.Where(x => x.CateId == cateId);

            //如果查询的关键字不为空
            if (!string.IsNullOrEmpty(keyword))
                goods = goods.Where(x => x.Name.Contains(keyword));

            //开始连表            连接表           主表外键      连接表的主键    把两个表的字段结合起来 新建一个模型
            var list = goods.Join(_db.Categories, x => x.CateId, y => y.Id, (x, y) => new GoodModel
            {
                Name = x.Name,
                CateId = x.CateId,
                CategoryName = y.CateName,
                Cover = x.Cover,
                Id = x.Id,
                Price = x.Price,
                Stock = x.Stock
            })
                //执行SQL查询
                .ToList();
            return list;
        }
        /// <summary>
        /// 查询分类接口 返回；类型商品
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public List<SelectCategories> GetSelectCategories()
        {
            //获取分类操作
            var catesProduct = _db.Categories.AsQueryable()
            .Select(cates => new SelectCategories
            {
                CateId = cates.Id,
                CategoryName = cates.CateName,
                ProductList = _db.Goods
                .Where(Good => cates.Id == Good.CateId)
                .Select(Good => new Goodtype
                {
                    Id = Good.Id,
                    Name = Good.Name,
                }).ToList()
            }).ToList();
            return catesProduct;
        }
        /// <summary>
        /// 查找商品类型并返回对应商品
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public List<SelectCategories> GetSelectCategoriesOnce(string cateName)
        {
            //获取商品类型
            var categorieProduct = _db.Categories.AsQueryable()
                .Where(cates => cates.CateName.Contains(cateName))
                .Select(cates => new SelectCategories
                {
                    CateId = cates.Id,
                    CategoryName = cates.CateName,
                    ProductList = _db.Goods.Where(Good => cates.Id == Good.CateId)
                    .Select(Good => new Goodtype
                    {
                        Id = Good.Id,
                        Name = Good.Name,
                    }).ToList(),
                }).ToList();
            return categorieProduct;
        }

        //方法注入
        /// <summary>
        /// 生命周期 判断我们的对象是不是同一个对象
        /// </summary>
        /// <param name="dataServices2"></param>
        /// <returns></returns>
        [HttpPost]
        public string GetDate([FromServices] IDataServices dataServices2)
        {
            //控制器获取的服务
            _dataService.GetData();

            //接口方法获取服务
            dataServices2.GetData();

            dataServices2.GetHashCode();

            //GetHashCode获取对象的HashCode判断HashCode是否一致 判断我们的对象是不是同一个对象

            return "1的hashcode=" + _dataService.GetHashCode() + "  2的hashcode=" + dataServices2.GetHashCode();
        }

        /// <summary>
        /// Singleton 对象创建后  会一直存在 直到应用程序结束
        /// </summary>
        /// <param name="singletonService"></param>
        /// <returns></returns>
        [HttpPost]
        public string Singleton([FromServices] ISingletonService singletonService)
        {
            //启动 应用程序后 无论怎么获取 都是那个对象 
            return "1的hashcode=" + _singletonService.GetHashCode() + "  2的hashcode=" + singletonService.GetHashCode();
        }

        /// <summary>
        /// Transient 每一次获取这个对象 都会是新的对象
        /// </summary>
        /// <param name="transientService"></param>
        /// <returns></returns>
        [HttpPost]
        public string Transient([FromServices] ITransientService transientService)
        {
            //无论怎么获取 都是新的对象 
            return "1的hashcode=" + _transientService.GetHashCode() + "  2的hashcode=" + transientService.GetHashCode();
        }

        /// <summary>
        /// Scoped 多次请求 不是同一个对象
        /// </summary>
        /// <param name="scopedService"></param>
        /// <returns></returns>
        [HttpPost]
        public string Scoped([FromServices] IScopedService scopedService)
        {
            //在一次请求 无论获取多少次 都是同一个对象 
            return "1的hashcode=" + _scopedService.GetHashCode() + "  2的hashcode=" + scopedService.GetHashCode();
        }
    }
}
